home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / p_aa4re / bb212src / bbsrtmod.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-02-23  |  29.9 KB  |  804 lines

  1. (*===========================================================================*)
  2. (* Procedure to send/receive things to a telephone modem                     *)
  3. (*                                                                           *)
  4. (*   Copyright 1988, 1989, 1990 by H. Roy Engehausen.  All rights reserved.  *)
  5. (*                                                                           *)
  6. (*===========================================================================*)
  7.  
  8. (*===========================================================================*)
  9. (* Main procedure                                                            *)
  10. (*                                                                           *)
  11. (*    Parm = 0 -- Data                                                       *)
  12. (*           1 -- Data                                                       *)
  13. (*           2 -- General Poll                                               *)
  14. (*           3 -- Data Poll                                                  *)
  15. (*           4 -- Link Status Poll                                           *)
  16. (*           5 -- Data ack poll                                              *)
  17. (*===========================================================================*)
  18.  
  19. {$UNDEF DEBUG_UPMODEM}
  20.  
  21. PROCEDURE send_recv_modem(tnc_cmd_data : BYTE);
  22.  
  23.   VAR
  24.     b      : BOOLEAN;
  25.     i      : BYTE;
  26.     regs   : REGISTERS;
  27.     s      : CHAR;
  28.     set_dx : BYTE;
  29.  
  30.   (*=========================================================================*)
  31.   (* Short wait                                                              *)
  32.   (*=========================================================================*)
  33.  
  34.   PROCEDURE short_wait;
  35.  
  36.     VAR
  37.       i : BYTE;
  38.  
  39.     BEGIN;
  40.  
  41.       IF active_tcb^.tcb_type = th_main THEN
  42.         DELAY(700)
  43.       ELSE
  44.         task_wait(1, FALSE);
  45.  
  46.     END;
  47.  
  48.  
  49.   (*=========================================================================*)
  50.   (* Set null answer procedure                                               *)
  51.   (*=========================================================================*)
  52.  
  53.   PROCEDURE set_null;
  54.     BEGIN;
  55.  
  56.       active_tcb^.tnc_null := TRUE;
  57.  
  58.       active_tcb^.tnc_type := t_to_h_ok;
  59.  
  60.       active_tcb^.tnc_data.str_data    := '';
  61.       active_tcb^.tnc_data.long_length := 0;
  62.  
  63.     END;
  64.  
  65.   (*=========================================================================*)
  66.   (* Queue received data onto thread control block                           *)
  67.   (*=========================================================================*)
  68.  
  69.   PROCEDURE queue_received_data;
  70.  
  71.     VAR
  72.       data_save : str_mixed;
  73.       i         : WORD;
  74.       add_tcb   : tcb_ptr;
  75.  
  76.     BEGIN;
  77.  
  78.       WITH active_tcb^.tnc_tth^ DO
  79.         BEGIN;
  80.  
  81.           (*-----------------------------------------------------------------*)
  82.           (* If we have no data, then we leave                               *)
  83.           (*-----------------------------------------------------------------*)
  84.  
  85.           i := data67_count;
  86.           IF i = 0 THEN
  87.             EXIT;
  88.  
  89.           (*-----------------------------------------------------------------*)
  90.           (* Save buffer.                                                    *)
  91.           (*-----------------------------------------------------------------*)
  92.  
  93.           IF tnc_cmd_data < 2 THEN
  94.             data_save := active_tcb^.tnc_data;
  95.  
  96.           (*-----------------------------------------------------------------*)
  97.           (* Move data from buffer to tnc data area                          *)
  98.           (*-----------------------------------------------------------------*)
  99.  
  100.           active_tcb^.tnc_data.long_length := i;
  101.           MOVE(data67, active_tcb^.tnc_data.long_data, i);
  102.           IF i > 255 THEN
  103.             i := 255;
  104.           active_tcb^.tnc_data.str_data[0] := CHR(i);
  105.  
  106.           (*-----------------------------------------------------------------*)
  107.           (* Clear the buffer                                                *)
  108.           (*-----------------------------------------------------------------*)
  109.  
  110.           data67_count := 0;
  111.  
  112.         END;
  113.  
  114.       (*---------------------------------------------------------------------*)
  115.       (* Add the data to the queue                                           *)
  116.       (*---------------------------------------------------------------------*)
  117.  
  118.       active_tcb^.tnc_type := t_to_h_conn;
  119.  
  120.       i := 1;
  121.       WHILE (i <= active_port^.max_chan)
  122.                                     AND (active_port^.connected^[i] = NIL) DO
  123.         INC(i);
  124.  
  125.       IF i <= active_port^.max_chan THEN
  126.         add_tcb := active_port^.connected^[i]
  127.       ELSE
  128.         add_tcb := active_tcb;
  129.  
  130.       add_tnc_queue(add_tcb, add_tcb^.channel);
  131.  
  132.       {$IFDEF DEBUG}
  133.         WRITELN('ADDQ=', active_tcb^.tnc_data.long_length, '=',
  134.                          active_tcb^.tnc_data.str_data);
  135.         WRITELN('TO=',add_tcb^.port_chan_s, '-', add_tcb^.channel);
  136.         DELAY(700);
  137.       {$ENDIF}
  138.  
  139.       (*---------------------------------------------------------------------*)
  140.       (* Restore buffer                                                      *)
  141.       (*---------------------------------------------------------------------*)
  142.  
  143.       IF tnc_cmd_data < 2 THEN
  144.         active_tcb^.tnc_data := data_save;
  145.  
  146.     END;
  147.  
  148.   (*=========================================================================*)
  149.   (* Get data from telephone modem and put in buffer.  Queue as needed       *)
  150.   (*=========================================================================*)
  151.  
  152.   PROCEDURE receive_telephone_modem;
  153.  
  154.     VAR
  155.       b_cnt         : WORD;
  156.       first_time    : BOOLEAN;
  157.       master_thread : BOOLEAN;
  158.       pause_expire  : LONGINT;
  159.  
  160.     CONST
  161.       buffer_size     = 254;
  162.       pause_to        = 8;
  163.       send_buffer_cnt = 100;
  164.  
  165.     LABEL
  166.       start_buffer_over;
  167.  
  168.     BEGIN;
  169.  
  170.       master_thread := active_tcb^.tcb_type = th_main;
  171.  
  172.       (*---------------------------------------------------------------------*)
  173.       (* Grab the locks                                                      *)
  174.       (*---------------------------------------------------------------------*)
  175.  
  176.       get_port_semaphore;
  177.       task_switch;
  178.  
  179.       WITH active_tcb^.tnc_tth^ DO
  180.         BEGIN;
  181.  
  182.           (*-----------------------------------------------------------------*)
  183.           (* Initialize things                                               *)
  184.           (*-----------------------------------------------------------------*)
  185.  
  186.           b_cnt := data67_count;
  187.  
  188. start_buffer_over:
  189.  
  190.           regs.DI := OFS(data67[b_cnt + 1]);
  191.           regs.ES := SEG(data67);
  192.           regs.DX := set_dx;
  193.  
  194.           (*-----------------------------------------------------------------*)
  195.           (* Force the timer to initialize                                   *)
  196.           (*-----------------------------------------------------------------*)
  197.  
  198.           regs.CX    := 1;
  199.           first_time := TRUE;
  200.  
  201.           (*-----------------------------------------------------------------*)
  202.           (* Loop until we see a pause in incoming data                      *)
  203.           (*-----------------------------------------------------------------*)
  204.  
  205.           REPEAT;
  206.  
  207.             (*---------------------------------------------------------------*)
  208.             (* Calculate the current time                                    *)
  209.             (*---------------------------------------------------------------*)
  210.  
  211.             IF master_thread THEN
  212.               calc_up_time
  213.             ELSE
  214.               task_switch;
  215.  
  216.             (*---------------------------------------------------------------*)
  217.             (* If we got data the last time around, calculate new timeout    *)
  218.             (*---------------------------------------------------------------*)
  219.  
  220.             IF (regs.CX <> 0) OR first_time THEN
  221.               pause_expire := up_time + pause_to;
  222.  
  223.             first_time := regs.CX <> 0;
  224.  
  225.             {$IFDEF DEBUG_UPMODEM}
  226.               WRITELN(regs.CX, ' -- ', pause_time, ' -- ', up_time);
  227.             {$ENDIF}
  228.  
  229.             (*---------------------------------------------------------------*)
  230.             (* Get data                                                      *)
  231.             (*---------------------------------------------------------------*)
  232.  
  233.             regs.AX := $0B00;
  234.             regs.CX := buffer_size - b_cnt;
  235.  
  236.             signal_place^ := $0200 + LO(signal_place^);
  237.  
  238.             INTR(tnc_interrupt, regs);
  239.  
  240.             signal_place^ := $F800 + LO(signal_place^);
  241.  
  242.             (*---------------------------------------------------------------*)
  243.             (* Bump counter                                                  *)
  244.             (*---------------------------------------------------------------*)
  245.  
  246.             INC(b_cnt, regs.CX);
  247.  
  248.             (*---------------------------------------------------------------*)
  249.             (* If buffer overflows then queue it and start over              *)
  250.             (*---------------------------------------------------------------*)
  251.  
  252.             IF b_cnt >= send_buffer_cnt THEN
  253.               BEGIN;
  254.                 data67_count := b_cnt;
  255.                 queue_received_data;
  256.                 free_semaphore(semaphore_interrupts);
  257.                 get_semaphore(semaphore_interrupts, sem_shared, FALSE);
  258.                 b_cnt := 0;
  259.                 GOTO start_buffer_over;
  260.               END;
  261.  
  262.             (*---------------------------------------------------------------*)
  263.             (* Loop around until timeout                                     *)
  264.             (*---------------------------------------------------------------*)
  265.  
  266.           UNTIL (pause_expire < up_time) AND (regs.CX = 0);
  267.  
  268.           (*-----------------------------------------------------------------*)
  269.           (* Set the result so far and leave                                 *)
  270.           (*-----------------------------------------------------------------*)
  271.  
  272.           data67_count := b_cnt;
  273.  
  274.         END;
  275.  
  276.       (*---------------------------------------------------------------------*)
  277.       (* Drop the locks                                                      *)
  278.       (*---------------------------------------------------------------------*)
  279.  
  280.       free_port_semaphore;
  281.       task_switch;
  282.  
  283.     END;
  284.  
  285.   (*=========================================================================*)
  286.   (* Send data to telephone modem                                            *)
  287.   (*=========================================================================*)
  288.  
  289.   {$UNDEF TRACE_ME}
  290.  
  291.   PROCEDURE send_telephone_modem;
  292.  
  293.  
  294.     TYPE
  295.       x  = ARRAY[1..10] OF CHAR;
  296.  
  297.     VAR
  298.       i : BYTE;
  299.  
  300.       {$IFDEF TRACE_ME}
  301.         p : ^x;
  302.       {$ENDIF}
  303.  
  304.     BEGIN;
  305.  
  306.  
  307.       {$IFDEF TRACE_ME}
  308.         trace_data('MW', active_tcb^.tnc_data.long_length, NIL,
  309.                                                 active_tcb^.tnc_data.str_data);
  310.       {$ENDIF}
  311.  
  312.       (*---------------------------------------------------------------------*)
  313.       (* Wait for buffer empty before sending                                *)
  314.       (*---------------------------------------------------------------------*)
  315.  
  316.       REPEAT
  317.  
  318.         task_switch;
  319.  
  320.         regs.AX := $0300;
  321.         regs.DX := set_dx;
  322.         INTR(tnc_interrupt, regs);
  323.  
  324.       UNTIL (regs.AH AND lsr_8250_thre) <> 0;
  325.  
  326.       (*---------------------------------------------------------------------*)
  327.       (* Send the data directly from the thread's buffer                     *)
  328.       (*---------------------------------------------------------------------*)
  329.  
  330.       regs.CX := active_tcb^.tnc_data.long_length;
  331.       regs.DI := OFS(active_tcb^.tnc_data.long_data);
  332.       regs.ES := SEG(active_tcb^.tnc_data.long_data);
  333.  
  334.       REPEAT
  335.  
  336.         regs.AX := $0A00;
  337.         regs.DX := set_dx;
  338.  
  339.         (*-------------------------------------------------------------------*)
  340.         (* Grab the locks                                                    *)
  341.         (*-------------------------------------------------------------------*)
  342.  
  343.         get_port_semaphore;
  344.         task_switch;
  345.  
  346.         signal_place^ := $0200 + LO(signal_place^);
  347.  
  348.         INTR(tnc_interrupt, regs);
  349.  
  350.         signal_place^ := $F800 + LO(signal_place^);
  351.  
  352.         (*-------------------------------------------------------------------*)
  353.         (* Drop the locks                                                    *)
  354.         (*-------------------------------------------------------------------*)
  355.  
  356.         free_port_semaphore;
  357.         task_switch;
  358.  
  359.         IF regs.CX <> 0 THEN
  360.           BEGIN;
  361.             FOR i := 1 TO 20 DO
  362.               task_switch;
  363.  
  364.             {$IFDEF TRACE_ME}
  365.               WRITE('Non-zero CX = ', regs.CX);
  366.               p := PTR(regs.ES, regs.DI);
  367.               FOR i := 1 TO 10 DO
  368.                 WRITE(p^[i]);
  369.               WRITELN;
  370.             {$ENDIF}
  371.  
  372.           END;
  373.  
  374.       UNTIL regs.CX = 0;
  375.  
  376.     END;
  377.  
  378.   (*=========================================================================*)
  379.   (* Send a string                                                           *)
  380.   (*=========================================================================*)
  381.  
  382.   PROCEDURE send_telephone_modem_string;
  383.  
  384.     BEGIN;
  385.  
  386.       active_tcb^.tnc_data.long_length :=
  387.                                          LENGTH(active_tcb^.tnc_data.str_data);
  388.  
  389.       send_telephone_modem;
  390.  
  391.  
  392.     END;
  393.  
  394.   (*=========================================================================*)
  395.   (* Generate link status change                                             *)
  396.   (*=========================================================================*)
  397.  
  398.   FUNCTION generate_link_status_change : BOOLEAN;
  399.  
  400.     VAR
  401.       b : BOOLEAN;
  402.  
  403.     BEGIN;
  404.  
  405.       (*---------------------------------------------------------------------*)
  406.       (* See if we are connected                                             *)
  407.       (*---------------------------------------------------------------------*)
  408.  
  409.       b := test_phone_connect;
  410.  
  411.       (*---------------------------------------------------------------------*)
  412.       (* Assume we are going to send something                               *)
  413.       (*---------------------------------------------------------------------*)
  414.  
  415.       generate_link_status_change := TRUE;
  416.  
  417.       (*---------------------------------------------------------------------*)
  418.       (* If we are now connected and we weren't before then connect          *)
  419.       (*---------------------------------------------------------------------*)
  420.  
  421.       IF b AND NOT active_port^.port_modem_dcd THEN
  422.         BEGIN;
  423.  
  424.           active_tcb^.tnc_data.str_data := modem_conn;
  425.           active_tcb^.tnc_data.long_length :=
  426.                                          LENGTH(active_tcb^.tnc_data.str_data);
  427.  
  428.           active_tcb^.tnc_type := t_to_h_links;
  429.           active_tcb^.tnc_null := FALSE;
  430.  
  431.           active_port^.port_modem_dcd := TRUE;
  432.  
  433.           IF active_port^.modem_dial THEN
  434.             active_port^.modem_conn := TRUE;
  435.  
  436.           EXIT;
  437.  
  438.         END;
  439.  
  440.       (*---------------------------------------------------------------------*)
  441.       (* If we are now not connected and we were before then disconnect      *)
  442.       (*---------------------------------------------------------------------*)
  443.  
  444.       IF (NOT b) AND active_port^.port_modem_dcd THEN
  445.         BEGIN;
  446.  
  447.           active_tcb^.tnc_data.str_data := t_to_h_disc + 'MODEM';
  448.           active_tcb^.tnc_data.long_length :=
  449.                                          LENGTH(active_tcb^.tnc_data.str_data);
  450.  
  451.           active_tcb^.tnc_type := t_to_h_links;
  452.           active_tcb^.tnc_null := FALSE;
  453.  
  454.           active_port^.port_modem_dcd := FALSE;
  455.  
  456.           EXIT;
  457.  
  458.         END;
  459.  
  460.       (*---------------------------------------------------------------------*)
  461.       (* Status is quo                                                       *)
  462.       (*---------------------------------------------------------------------*)
  463.  
  464.       generate_link_status_change := FALSE;
  465.  
  466.     END;
  467.  
  468.   (*=========================================================================*)
  469.   (* Main line                                                               *)
  470.   (*=========================================================================*)
  471.  
  472.   BEGIN;
  473.  
  474.     {$IFDEF DEBUG}
  475.       WRITELN('SMODEM=', tnc_cmd_data, '=', active_tcb^.tnc_data.str_data);
  476.       DELAY(700);
  477.     {$ENDIF}
  478.  
  479.     (*-----------------------------------------------------------------------*)
  480.     (* Initialize                                                            *)
  481.     (*-----------------------------------------------------------------------*)
  482.  
  483.     set_dx := active_port^.com_number - 1;
  484.  
  485.     (*-----------------------------------------------------------------------*)
  486.     (* Hit the old modem!                                                    *)
  487.     (*-----------------------------------------------------------------------*)
  488.  
  489.     receive_telephone_modem;
  490.  
  491.     (*-----------------------------------------------------------------------*)
  492.     (* Execute                                                               *)
  493.     (*-----------------------------------------------------------------------*)
  494.  
  495.     CASE tnc_cmd_data OF
  496.  
  497.       (*---------------------------------------------------------------------*)
  498.       (* Outgoing data                                                       *)
  499.       (*---------------------------------------------------------------------*)
  500.  
  501.       0 : BEGIN;
  502.  
  503.             (*---------------------------------------------------------------*)
  504.             (* Send the data                                                 *)
  505.             (*---------------------------------------------------------------*)
  506.  
  507. {$IFDEF DEBUG}
  508.   WRITELN('STM');
  509. {$ENDIF}
  510.  
  511.             send_telephone_modem;
  512.  
  513.             (*---------------------------------------------------------------*)
  514.             (* Get anything waiting and empty the buffer                     *)
  515.             (*---------------------------------------------------------------*)
  516.  
  517.  
  518. {$IFDEF DEBUG}
  519.   WRITELN('RTM');
  520. {$ENDIF}
  521.  
  522.             receive_telephone_modem;
  523.  
  524.             (*---------------------------------------------------------------*)
  525.             (* Fake a null response                                          *)
  526.             (*---------------------------------------------------------------*)
  527.  
  528.             set_null;
  529.  
  530.           END;
  531.  
  532.       (*---------------------------------------------------------------------*)
  533.       (* Outgoing command                                                    *)
  534.       (*---------------------------------------------------------------------*)
  535.  
  536.       1 : BEGIN;
  537.  
  538.             s := UPCASE(active_tcb^.tnc_data.str_data[1]);
  539.  
  540.             CASE s OF
  541.  
  542.               (*-------------------------------------------------------------*)
  543.               (* Link state                                                  *)
  544.               (*-------------------------------------------------------------*)
  545.  
  546.               'L':
  547.                 BEGIN;
  548.  
  549.                   active_tcb^.tnc_data.str_data    := '0 0 0 0 0 0';
  550.                   active_tcb^.tnc_data.long_length :=
  551.                                         LENGTH(active_tcb^.tnc_data.str_data);
  552.  
  553.                   active_tcb^.tnc_null := FALSE;
  554.                   active_tcb^.tnc_type := t_to_h_okmsg;
  555.  
  556.                   (*---------------------------------------------------------*)
  557.                   (* Set receive buffer waiting                              *)
  558.                   (*---------------------------------------------------------*)
  559.  
  560.                   IF (active_tcb^.tnc_in_chn <> NIL)
  561.                                 OR (active_tcb^.tnc_tth^.data67_count > 0) THEN
  562.                     active_tcb^.tnc_data.str_data[3] := '1';
  563.  
  564.                   (*---------------------------------------------------------*)
  565.                   (* Link status message waiting                             *)
  566.                   (*---------------------------------------------------------*)
  567.  
  568.                   b := test_phone_connect;
  569.  
  570.                   IF b XOR active_port^.port_modem_dcd THEN
  571.                     active_tcb^.tnc_data.str_data[1] := '1';
  572.  
  573.                   (*---------------------------------------------------------*)
  574.                   (* Link status                                             *)
  575.                   (*---------------------------------------------------------*)
  576.  
  577.                   IF b THEN
  578.                     active_tcb^.tnc_data.str_data[11] := '1';
  579.  
  580.                   EXIT;
  581.  
  582.                 END;
  583.  
  584.               (*-------------------------------------------------------------*)
  585.               (* Disconnect                                                  *)
  586.               (*-------------------------------------------------------------*)
  587.  
  588.               'D' :
  589.                 BEGIN;
  590.  
  591.                   set_port_speed(active_port^.data_rate);
  592.  
  593.                   (*---------------------------------------------------------*)
  594.                   (* Loop thru two times                                     *)
  595.                   (*---------------------------------------------------------*)
  596.  
  597.                   FOR i := 1 TO 2 DO
  598.                     BEGIN;
  599.  
  600.                       (*-----------------------------------------------------*)
  601.                       (* Set port speed                                      *)
  602.                       (*-----------------------------------------------------*)
  603.  
  604.                    (* set_port_speed(active_port^.data_rate);*)
  605.  
  606.                       (*-----------------------------------------------------*)
  607.                       (* Drop DTR and RTS                                    *)
  608.                       (*-----------------------------------------------------*)
  609.  
  610.                       regs.AX := $0500;
  611.                       regs.DX := set_dx;
  612.  
  613.                       signal_place^ := $0200 + LO(signal_place^);
  614.  
  615.                       INTR(tnc_interrupt, regs);
  616.  
  617.                       signal_place^ := $F800 + LO(signal_place^);
  618.  
  619.                       (*-----------------------------------------------------*)
  620.                       (* Delay                                               *)
  621.                       (*-----------------------------------------------------*)
  622.  
  623.                       short_wait;
  624.  
  625.                       (*-----------------------------------------------------*)
  626.                       (* Raise DTR and RTS                                   *)
  627.                       (*-----------------------------------------------------*)
  628.  
  629.                       regs.AX := $0600;
  630.                       regs.DX := set_dx;
  631.  
  632.                       signal_place^ := $0200 + LO(signal_place^);
  633.  
  634.                       INTR(tnc_interrupt, regs);
  635.  
  636.                       signal_place^ := $F800 + LO(signal_place^);
  637.  
  638.                       (*-----------------------------------------------------*)
  639.                       (* Switch to command mode                              *)
  640.                       (*-----------------------------------------------------*)
  641.  
  642.                       short_wait;
  643.  
  644.                       active_tcb^.tnc_data.str_data := '+++';
  645.                       send_telephone_modem_string;
  646.  
  647.                       short_wait;
  648.  
  649.                       (*-----------------------------------------------------*)
  650.                       (* Hangup                                              *)
  651.                       (*-----------------------------------------------------*)
  652.  
  653.                       active_tcb^.tnc_data.str_data := 'ATH0' + cr;
  654.                       send_telephone_modem_string;
  655.  
  656.  
  657.                     END;
  658.  
  659.                   (*---------------------------------------------------------*)
  660.                   (* Now we send a DED mode error.  This tells everyone      *)
  661.                   (* that the disconnect was successful immediately          *)
  662.                   (* Yes.. this sounds weird but it's simulating a disconnect*)
  663.                   (* send to a channel that is not connected.  If we sent    *)
  664.                   (* an OK, then we would have to have a link status message *)
  665.                   (* later to say the DISC was successfull.                  *)
  666.                   (*---------------------------------------------------------*)
  667.  
  668.                   IF NOT active_port^.port_modem_dcd THEN
  669.                     BEGIN;
  670.                       active_tcb^.tnc_data.str_data    := 'LINE DISCONNECTED';
  671.                       active_tcb^.tnc_data.long_length :=
  672.                                          LENGTH(active_tcb^.tnc_data.str_data);
  673.  
  674.                       active_tcb^.tnc_null := FALSE;
  675.                       active_tcb^.tnc_type := t_to_h_badmsg;
  676.                     END
  677.                   ELSE
  678.                     set_null;
  679.  
  680.                   EXIT;
  681.  
  682.                 END;
  683.  
  684.               (*-------------------------------------------------------------*)
  685.               (* Connect                                                     *)
  686.               (*-------------------------------------------------------------*)
  687.  
  688.               'C' :
  689.                 BEGIN;
  690.  
  691.                   (*---------------------------------------------------------*)
  692.                   (* Change the "C" to "ATD" and add CR                      *)
  693.                   (*---------------------------------------------------------*)
  694.  
  695.                   active_tcb^.tnc_data.str_data := 'ATD' +
  696.                               COPY(active_tcb^.tnc_data.str_data, 2, 255) + cr;
  697.  
  698.                   (*---------------------------------------------------------*)
  699.                   (* We removed 1 character and added 4 for a net            *)
  700.                   (* increase of three in the length                         *)
  701.                   (*---------------------------------------------------------*)
  702.  
  703.                   INC(active_tcb^.tnc_data.long_length, 3);
  704.  
  705.                   (*---------------------------------------------------------*)
  706.                   (* Send data                                               *)
  707.                   (*---------------------------------------------------------*)
  708.  
  709.                   send_telephone_modem;
  710.  
  711.                   (*---------------------------------------------------------*)
  712.                   (* Null response                                           *)
  713.                   (*---------------------------------------------------------*)
  714.  
  715.                   set_null;
  716.  
  717.                 END;
  718.  
  719.               (*-------------------------------------------------------------*)
  720.               (* Invalid command                                             *)
  721.               (*-------------------------------------------------------------*)
  722.  
  723.               ELSE
  724.                 BEGIN;
  725.  
  726. WRITELN('Bad command -- ', active_tcb^.tnc_data.str_data);
  727. DELAY(800);
  728.  
  729.                   active_tcb^.tnc_data.str_data    := 'INVALID COMMAND -- '
  730.                                                + active_tcb^.tnc_data.str_data;
  731.                   active_tcb^.tnc_data.long_length :=
  732.                                          LENGTH(active_tcb^.tnc_data.str_data);
  733.  
  734.                   active_tcb^.tnc_null := FALSE;
  735.                   active_tcb^.tnc_type := t_to_h_badmsg;
  736.  
  737.                   EXIT;
  738.                 END;
  739.  
  740.             END; (*----- End command case statement -------------------------*)
  741.  
  742.           END; (*----- End outgoing command ---------------------------------*)
  743.  
  744.       (*---------------------------------------------------------------------*)
  745.       (* Poll                                                                *)
  746.       (*---------------------------------------------------------------------*)
  747.  
  748.       2..4:
  749.  
  750.           BEGIN;
  751.  
  752.             (*---------------------------------------------------------------*)
  753.             (* If link status is ok then see if we generate one              *)
  754.             (*---------------------------------------------------------------*)
  755.  
  756.             IF (tnc_cmd_data <> 3) AND generate_link_status_change THEN
  757.               EXIT;
  758.  
  759.             (*---------------------------------------------------------------*)
  760.             (* Receive any pending data                                      *)
  761.             (*---------------------------------------------------------------*)
  762.  
  763.             receive_telephone_modem;
  764.  
  765.             (*---------------------------------------------------------------*)
  766.             (* If we are going to pull data out then queue data              *)
  767.             (*---------------------------------------------------------------*)
  768.  
  769.             IF tnc_cmd_data < 4 THEN
  770.               queue_received_data;
  771.  
  772.             (*---------------------------------------------------------------*)
  773.             (* Anything in the chain?                                        *)
  774.             (*---------------------------------------------------------------*)
  775.  
  776.             IF active_tcb^.tnc_in_chn <> NIL THEN
  777.               b := tnc_data_queued
  778.             ELSE
  779.               b := FALSE;
  780.  
  781.             (*---------------------------------------------------------------*)
  782.             (* Set null switch                                               *)
  783.             (*---------------------------------------------------------------*)
  784.  
  785.             IF NOT b THEN
  786.               set_null
  787.             ELSE
  788.               active_tcb^.tnc_null := FALSE;
  789.  
  790.           END;
  791.  
  792.       (*---------------------------------------------------------------------*)
  793.       (* Ignore anything else                                                *)
  794.       (*---------------------------------------------------------------------*)
  795.  
  796.       ELSE
  797.         BEGIN;
  798.           WRITELN('TNC CODE - ', tnc_cmd_data);
  799.         END;
  800.  
  801.     END; (*----- End case statement on transaction code ---------------------*)
  802.  
  803.   END; (*----- End main send/receive Modem ----------------------------------*)
  804.